﻿using Devonline.Communication.Messages;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.OData.Query;
using Microsoft.Extensions.Caching.Distributed;

namespace Devonline.Identity.Admin.Controllers;

[Route("api/[controller]")]
[ApiController]
[SecurityHeaders]
[Authorize(Roles = GROUP_MAINTAINERS)]
public class AccessRulesController : ControllerBase
{
    private readonly IdentityDbContext _context;
    private readonly IDistributedCache _cache;
    private readonly IMessageCommunicator _communicator;
    private readonly IDataService<IdentityDbContext, AccessRule> _dataService;
    public AccessRulesController(
        IdentityDbContext context,
        IDistributedCache cache,
        IMessageCommunicator communicator,
        IDataService<IdentityDbContext, AccessRule> dataService
        )
    {
        _context = context;
        _cache = cache;
        _dataService = dataService;
        _communicator = communicator;
    }

    [HttpGet, EnableQuery]
    public IActionResult Get() => Ok(_dataService.GetQueryable());
    [HttpPost]
    public async Task<IActionResult> CreateAsync(AccessRuleViewModel entitySet)
    {
        entitySet = await _dataService.AddAsync(entitySet);
        await RefreshUserInfo(entitySet.IdentityType, new string[] { entitySet.IdentityId });
        return Ok(entitySet);
    }

    [HttpPut]
    public async Task<IActionResult> UpdateAsync(AccessRuleViewModel entitySet)
    {
        entitySet = await _dataService.UpdateAsync(entitySet);
        await RefreshUserInfo(entitySet.IdentityType, new string[] { entitySet.IdentityId });
        return Ok(entitySet);
    }

    [HttpDelete("{id}")]
    public async Task<IActionResult> DeleteAsync(string id)
    {
        var entitySet = await _dataService.GetAsync(id);
        await _dataService.DeleteAsync(id);
        await RefreshUserInfo(entitySet.IdentityType, new string[] { entitySet.IdentityId });
        return Ok();
    }

    [HttpGet("GetUserInfo/{userName}/{system}")]
    public async Task<IActionResult> GetUserInfoAsync(string userName, string system)
    {
        var userInfo = await _context.GetUserAccessResourcesAsync(_cache, userName ?? HttpContext.GetUserName());
        return Ok(new { user = userInfo.User, Resources = userInfo.ResourceTree.FirstOrDefault(x => x.Content == system)?.Children });
    }

    [HttpGet("UserHasPermission/{userName}")]
    public async Task<IActionResult> UserHasPermissionAsync(string userName, string resource) => Ok(await _context.UserHasPermissionAsync(_cache, userName ?? HttpContext.GetUserName(), resource));

    /// <summary>
    /// 更新用户授权相关缓存
    /// </summary>
    /// <returns></returns>
    private async Task RefreshUserInfo(IdentityType identityType, params string[] identities)
    {
        var users = await _context.GetIdentityUsers(identityType, identities);
        if (users.IsNotNullOrEmpty())
        {
            foreach (var user in users)
            {
                //更新用户授权相关缓存
                await _context.GetUserAccessResourcesAsync(_cache, user.UserName, true);

                //强制推送客户端更新
                await _communicator.SendAsync(Constants.CACHE_USER_INFO, user.UserName, MessageType.Cache);
            }
        }
    }
}